﻿namespace SuperStarRounds.DockingTasks
{
  using System;
  using System.Collections.Generic;
  using System.Drawing;
  using System.Linq;
  using System.Text;
  using System.Windows.Forms;

  using Localisation;

  using Models.WondrousItemModel;
  using Models.WondrousItemModel.Template;
  using Models.WondrousItemModel.Template.Parts;

  public partial class CreateWondrousItem : BaseDockingTask
  {
    /// <summary>
    /// Holds a reference to the Item Name box to allow spell checking overlays to operate on it.
    /// </summary>
    // ReSharper disable once NotAccessedField.Local
    private CustomPaintTextBox spchkItemName;

    /// <summary>
    /// Initializes a new instance of the <see cref="CreateWondrousItem" /> class.
    /// </summary>
    public CreateWondrousItem()
    {
      InitializeComponent();
    }

    private void CreateWondrousItem_Load(object sender, EventArgs e)
    {
      Base_Load();

      // Activate the input text boxes with spell checking
      spchkItemName = new CustomPaintTextBox(this, itemName, OwnerSuperStar.SpellChecker, OwnerSuperStar.SpellThesaurus);

      // localise the form and controls:
      LocaliseForm();

      SuperStarSplash.SuperStarSplash.SetStatus("Loading Initial Data Structures");
      ComboBoxContents.FillWithCasterLevelChoices(casterLevel);
      ComboBoxContents.FillWithSlotChoices(itemSlot);
      ComboBoxContents.FillWithWeightPostFixChoices(itemWeightPostfix);
      ComboBoxContents.FillWithRankChoices(wiRankChoices, 30);

      var settings = GetCurrentConfigurationSettings();
      var checkState = settings.GetInclusionCheckState();

      SkillHandlers.SetSkillList(checkState, wiSkillChoices);
      SkillHandlers.SetSubSkillList(checkState, wiSkillChoices.Text, wiSubSkillChoices);
      ResetContent(sender, e);
      ResetPriceDropDowns();
      ResetCreationFeats();
      ResetSpellSchools();
    }

    private void CreateWondrousItem_Shown(object sender, EventArgs e)
    {
      SetFocusToFirstControl();
    }

    private void CreateWondrousItem_FormClosing(object sender, FormClosingEventArgs e)
    {
      Base_FormClosing();
    }

    public override void LocaliseForm()
    {
      Text = Localize.WiFormTitle;

      // ToolBar Load and Save, Languages
      BtnLoadDesign.Text = Localize.LoadButtonLabel;
      BtnLoadDesign.ToolTipText = Localize.LoadButtonLabel;
      BtnSaveDesign.Text = Localize.SaveButtonLabel;
      BtnSaveDesign.ToolTipText = Localize.SaveButtonLabel;

      configNoOfficeDetected.Text = Localize.OfficeNotFound;
      btnCreateWordDoc.ToolTipText = Localize.OfficeWord;
      btnCreateExcelSheet.ToolTipText = Localize.OfficeExcel;
      btnCreateOpenOfficeDoc.ToolTipText = Localize.OfficeOpenOffice;
      btnCreateOpenOfficeWorksheet.ToolTipText = Localize.OfficeOpenOfficeCalc;

      btnCreateWordDoc.Visible = OfficeInterop.IsMicrosoftWordInstalled();
      btnCreateExcelSheet.Visible = OfficeInterop.IsMicrosoftExcelInstalled();
      btnCreateOpenOfficeWorksheet.Visible = btnCreateOpenOfficeDoc.Visible = OfficeInterop.IsOOfficeInstalled();
      configNoOfficeDetected.Visible = !(btnCreateWordDoc.Visible || btnCreateExcelSheet.Visible || btnCreateOpenOfficeDoc.Visible);

      wordCountLabel.Text = Localize.WondrousItemTabWordCountLabel;
      safeWordCountLabel.Text = Localize.WondrousItemTabSafeWordCountLabel;

      // default to AutoCalc Costs
      itemCost1.ReadOnly = itemCost2.ReadOnly = itemCost3.ReadOnly = itemCost4.ReadOnly = itemCost5.ReadOnly = autoCalcCosts.Checked = true;

      // Base Detail Tab
      wiBasicTab.Text = Localize.WondrousItemTabNameBasicDetails;

      itemNameLabel.Text = Localize.WondrousItemTabItemNameLabel;
      itemNameLabel.Location = LocalPositionAdjust(new Point(137, 8), 0 - itemNameLabel.Size.Width);

      slotLabel.Text = Localize.WondrousItemTabSlotLabel;
      slotLabel.Location = LocalPositionAdjust(new Point(137, 34), 0 - slotLabel.Size.Width);

      itemWeightLabel.Text = Localize.WondrousItemTabWeightLabel;
      itemWeightLabel.Location = LocalPositionAdjust(new Point(137, 60), 0 - itemWeightLabel.Size.Width);

      // Description Tab
      wiDescription.Text = Localize.WondrousItemTabDescription;

      markUpBBLabel.Text = Localize.WondrousItemTabMarkUpLabel;

      // Aura's Tab
      wiAurasTab.Text = Localize.WondrousItemTabNameAuraSelection;

      aura1Label.Text = Localize.WondrousItemTabAura1Label;
      aura1Label.Location = LocalPositionAdjust(new Point(137, 8), 0 - aura1Label.Size.Width);

      aura2Label.Text = Localize.WondrousItemTabAura2Label;
      aura2Label.Location = LocalPositionAdjust(new Point(137, 34), 0 - aura2Label.Size.Width);

      aura3Label.Text = Localize.WondrousItemTabAura3Label;
      aura3Label.Location = LocalPositionAdjust(new Point(137, 60), 0 - aura3Label.Size.Width);

      aura4Label.Text = Localize.WondrousItemTabAura4Label;
      aura4Label.Location = LocalPositionAdjust(new Point(137, 86), 0 - aura4Label.Size.Width);

      // Creation Feats Tab
      wiCreationFeats.Text = Localize.WondrousItemTabNameCreationFeats;

      itemLabelFeat1.Text = Localize.WondrousItemTabCreationFeat1Label;
      itemLabelFeat1.Location = LocalPositionAdjust(new Point(137, 8), 0 - itemLabelFeat1.Size.Width);

      itemLabelFeat2.Text = Localize.WondrousItemTabCreationFeat2Label;
      itemLabelFeat2.Location = LocalPositionAdjust(new Point(137, 34), 0 - itemLabelFeat2.Size.Width);

      itemLabelFeat3.Text = Localize.WondrousItemTabCreationFeat3Label;
      itemLabelFeat3.Location = LocalPositionAdjust(new Point(137, 60), 0 - itemLabelFeat3.Size.Width);

      // Creation Spells Tab
      wiCreationSpells.Text = Localize.WondrousItemTabNameCreationSpells;

      itemSpellLabel1.Text = Localize.WondrousItemTabCreationSpell1Label;
      itemSpellLabel1.Location = LocalPositionAdjust(new Point(137, 8), 0 - itemSpellLabel1.Size.Width);

      itemSpellLabel2.Text = Localize.WondrousItemTabCreationSpell2Label;
      itemSpellLabel2.Location = LocalPositionAdjust(new Point(137, 34), 0 - itemSpellLabel2.Size.Width);

      itemSpellLabel3.Text = Localize.WondrousItemTabCreationSpell3Label;
      itemSpellLabel3.Location = LocalPositionAdjust(new Point(137, 60), 0 - itemSpellLabel3.Size.Width);

      itemSpellLabel4.Text = Localize.WondrousItemTabCreationSpell4Label;
      itemSpellLabel4.Location = LocalPositionAdjust(new Point(137, 86), 0 - itemSpellLabel4.Size.Width);

      itemSpellLabel5.Text = Localize.WondrousItemTabCreationSpell5Label;
      itemSpellLabel5.Location = LocalPositionAdjust(new Point(137, 112), 0 - itemSpellLabel5.Size.Width);

      itemSpellLabel6.Text = Localize.WondrousItemTabCreationSpell6Label;
      itemSpellLabel6.Location = LocalPositionAdjust(new Point(137, 138), 0 - itemSpellLabel6.Size.Width);

      casterLevelLabel.Text = Localize.WondrousItemTabCasterLevelLabel;
      casterLevelLabel.Location = LocalPositionAdjust(new Point(239, 164), 0 - casterLevelLabel.Size.Width);

      // Creation Other Tab
      wiCreationOther.Text = Localize.WondrousItemTabNameOtherCreation;

      // Pricing Tab
      wiPricing.Text = Localize.WondrousItemTabPriceNCostLabel;

      autoCalcCosts.Text = Localize.WondrousItemTabAutoCalcCostInstruction;

      priceAndCostLabel.Text = Localize.WondrousItemTabPriceNCostLabel + AdvisorStrings.SuperStar_LocaliseTabWondrousItemTabPage__1;
      priceAndCostLabel.Location = LocalPositionAdjust(new Point(137, 34), 0 - priceAndCostLabel.Size.Width);

      launchPriceHelper.Text = Localize.WondrousItemTabPriceHelperLabel;

      itemEntryPreview.Text = Localize.WondrousItemTabFormattedLabel;
      bbEntryPanel.Text = Localize.WondrousItemTabPaizoBbEntryLabel;

      // copy buttons
      BtnName.Text = Localize.WondrousItemTabCopyNameLabel;
      BtnEntry.Text = Localize.WondrousItemTabCopyEntryLabel;
      BtnCopyFormatted.Text = Localize.WondrousItemTabCopyFormattedLabel;
    }

    /// <summary>
    /// Provides a standard event for controls with effects that may alter selection
    /// content and configuration of the application.
    /// </summary>
    /// <param name="sender">Holds the object instantiating this event</param>
    /// <param name="e">Holds the event arguments</param>
    public override void ResetContent(object sender, EventArgs e)
    {
      // Reset the spell content of the spell choice controls.
      ResetAllSpellLists(sender, e);

      // Reset the skill choices
      var settings = GetCurrentConfigurationSettings();
      var checkState = settings.GetInclusionCheckState();

      SkillHandlers.SetSkillList(checkState, wiSkillChoices);
      SkillHandlers.SetSubSkillList(checkState, wiSkillChoices.Text, wiSubSkillChoices);
    }

    /// <summary>
    /// Provides a standard event for controls with effects that may alter the available spells
    /// in the spell selection controls (e.g. content options.
    /// </summary>
    /// <param name="sender">Holds the object instantiating this event</param>
    /// <param name="e">Holds the event arguments</param>
    private void ResetAllSpellLists(object sender, EventArgs e)
    {
      var settings = GetCurrentConfigurationSettings();
      var checkState = settings.GetInclusionCheckState();

      SpellHandlers.ResetSpellsList(checkState, itemSpellLevel1.Text, itemSpellSchool1.Text, itemSpell1);
      SpellHandlers.ResetSpellsList(checkState, itemSpellLevel2.Text, itemSpellSchool2.Text, itemSpell2);
      SpellHandlers.ResetSpellsList(checkState, itemSpellLevel3.Text, itemSpellSchool3.Text, itemSpell3);
      SpellHandlers.ResetSpellsList(checkState, itemSpellLevel4.Text, itemSpellSchool4.Text, itemSpell4);
      SpellHandlers.ResetSpellsList(checkState, itemSpellLevel5.Text, itemSpellSchool5.Text, itemSpell5);
      SpellHandlers.ResetSpellsList(checkState, itemSpellLevel6.Text, itemSpellSchool6.Text, itemSpell6);

      SpellHandlers.SetSubSchoolList(aura1School.Text, aura1SubSchool);
      SpellHandlers.SetSubSchoolList(aura2School.Text, aura2SubSchool);
      SpellHandlers.SetSubSchoolList(aura3School.Text, aura3SubSchool);
      SpellHandlers.SetSubSchoolList(aura4School.Text, aura4SubSchool);

      UpdateWondrousItemPostEntry(sender, e);
    }

    /// <summary>
    /// Reset the content of price post fix selection controls
    /// </summary>
    private void ResetPriceDropDowns()
    {
      // reset price dropdowns
      ComboBoxContents.FillWithPricePostFixChoices(itemPrice1Postfix);
      ComboBoxContents.FillWithPricePostFixChoices(itemPrice2Postfix);
      ComboBoxContents.FillWithPricePostFixChoices(itemPrice3Postfix);
      ComboBoxContents.FillWithPricePostFixChoices(itemPrice4Postfix);
      ComboBoxContents.FillWithPricePostFixChoices(itemPrice5Postfix);
    }

    /// <summary>
    /// Reset the content of creation feat selection controls
    /// </summary>
    private void ResetCreationFeats()
    {
      ComboBoxContents.FillWithCreationFeatChoices(itemFeat1);
      ComboBoxContents.FillWithCreationFeatChoices(itemFeat2);
      ComboBoxContents.FillWithCreationFeatChoices(itemFeat3);
    }

    /// <summary>
    /// Reset the content of spell school selection controls
    /// </summary>
    private void ResetSpellSchools()
    {
      ComboBoxContents.FillWithSpellSchoolChoices(itemSpellSchool1);
      ComboBoxContents.FillWithSpellSchoolChoices(itemSpellSchool2);
      ComboBoxContents.FillWithSpellSchoolChoices(itemSpellSchool3);
      ComboBoxContents.FillWithSpellSchoolChoices(itemSpellSchool4);
      ComboBoxContents.FillWithSpellSchoolChoices(itemSpellSchool5);
      ComboBoxContents.FillWithSpellSchoolChoices(itemSpellSchool6);
    }

    /// <summary>
    /// Utility method for showing and hiding the submission copy buttons
    /// </summary>
    /// <param name="visibility">true shows the controls, false hides them</param>
    private void ShowMyEntryControls(bool visibility)
    {
      entryTabs.Visible = visibility;
      BtnName.Visible = visibility;
      BtnEntry.Visible = visibility;
    }

    /// <summary>
    /// Handles the copy formatted entry button click.
    /// </summary>
    /// <param name="sender">Holds the object instantiating this event</param>
    /// <param name="e">Holds the event arguments</param>
    private void BtnCopyFormatted_Click(object sender, EventArgs e)
    {
      entryPreview.SelectAll();
      entryPreview.Copy();
      MessageBox.Show(Localize.InfoFormattedEntryInBufferText, Localize.InfoFormattedEntryInBufferText, MessageBoxButtons.OK, MessageBoxIcon.Information);
    }

    /// <summary>
    /// Creates a new excel document containing the formatted entry for the current
    /// active tab, leaving excel open for the user to edit and save.
    /// </summary>
    /// <param name="sender">Holds the object instantiating this event</param>
    /// <param name="e">Holds the event arguments</param>
    private void BtnCreateExcelSheet_Click(object sender, EventArgs e)
    {
      try
      {
        OfficeInterop.ExportRichTextToMicrosoftExcel(entryPreview);
      }
      catch (Exception)
      {
        MessageBox.Show(
          AdvisorStrings.SuperStar_BtnCreateOfficeDoc_Click_, AdvisorStrings.SuperStar_BtnCreateOfficeDoc_Click_Office_Interop_Failure,
          MessageBoxButtons.OK, MessageBoxIcon.Exclamation);

        btnCreateExcelSheet.Visible = btnCreateWordDoc.Visible = false; // disable both as they are from same vendor
        configNoOfficeDetected.Visible = !(btnCreateWordDoc.Visible || btnCreateExcelSheet.Visible || btnCreateOpenOfficeDoc.Visible || btnCreateOpenOfficeWorksheet.Visible);
      }
    }

    /// <summary>
    /// Creates a new open office write document containing the formatted entry for the current
    /// active tab, leaving it open for the user to edit and save.
    /// </summary>
    /// <param name="sender">Holds the object instantiating this event</param>
    /// <param name="e">Holds the event arguments</param>
    private void BtnCreateOpenOfficeDoc_Click(object sender, EventArgs e)
    {
      try
      {
        OfficeInterop.ExportRichTextToOpenOfficeWrite(entryPreview);
      }
      catch (Exception)
      {
        MessageBox.Show(
          AdvisorStrings.SuperStar_BtnCreateOpenOfficeDoc_Click_,
          AdvisorStrings.SuperStar_BtnCreateOpenOfficeDoc_Click_OpenOffice_Interop_Failure,
          MessageBoxButtons.OK, MessageBoxIcon.Exclamation);

        btnCreateOpenOfficeDoc.Visible = btnCreateOpenOfficeWorksheet.Visible = false; // disable both as they are from same vendor
        configNoOfficeDetected.Visible = !(btnCreateWordDoc.Visible || btnCreateExcelSheet.Visible || btnCreateOpenOfficeDoc.Visible || btnCreateOpenOfficeWorksheet.Visible);
      }
    }

    /// <summary>
    /// Creates a new open office worksheet containing the formatted entry for the current
    /// active tab, leaving it open for the user to edit and save.
    /// </summary>
    /// <param name="sender">Holds the object instantiating this event</param>
    /// <param name="e">Holds the event arguments</param>
    private void BtnCreateOpenOfficeWorksheet_Click(object sender, EventArgs e)
    {
      try
      {
        OfficeInterop.ExportRichTextToOpenOfficeWorksheet(entryPreview);
      }
      catch (Exception)
      {
        MessageBox.Show(
          AdvisorStrings.SuperStar_BtnCreateOpenOfficeDoc_Click_,
          AdvisorStrings.SuperStar_BtnCreateOpenOfficeDoc_Click_OpenOffice_Interop_Failure,
          MessageBoxButtons.OK, MessageBoxIcon.Exclamation);

        btnCreateOpenOfficeDoc.Visible = btnCreateOpenOfficeWorksheet.Visible = false; // disable both as they are from same vendor
        configNoOfficeDetected.Visible = !(btnCreateWordDoc.Visible || btnCreateExcelSheet.Visible || btnCreateOpenOfficeDoc.Visible || btnCreateOpenOfficeWorksheet.Visible);
      }
    }

    /// <summary>
    /// Creates a new word document containing the formatted wondrous item.
    /// </summary>
    /// <param name="sender">Holds the object instantiating this event</param>
    /// <param name="e">Holds the event arguments</param>
    private void BtnCreateWordDoc_Click(object sender, EventArgs e)
    {
      try
      {
        OfficeInterop.ExportRichTextToMicrosoftWord(entryPreview);
      }
      catch (Exception)
      {
        MessageBox.Show(
          AdvisorStrings.SuperStar_BtnCreateOfficeDoc_Click_, AdvisorStrings.SuperStar_BtnCreateOfficeDoc_Click_Office_Interop_Failure,
          MessageBoxButtons.OK, MessageBoxIcon.Exclamation);

        btnCreateExcelSheet.Visible = btnCreateWordDoc.Visible = false; // disable both as they are from same vendor
        configNoOfficeDetected.Visible = !(btnCreateWordDoc.Visible || btnCreateExcelSheet.Visible || btnCreateOpenOfficeDoc.Visible || btnCreateOpenOfficeWorksheet.Visible);
      }
    }

    /// <summary>
    /// Handles the copy entry button clicks.
    /// </summary>
    /// <param name="sender">Holds the object instantiating this event</param>
    /// <param name="e">Holds the event arguments</param>
    private void BtnEntry_Click(object sender, EventArgs e)
    {
      postEntry.SelectAll();
      postEntry.Copy();
      MessageBox.Show(Localize.InfoEntryInBufferText, Localize.InfoEntryInBufferTitle, MessageBoxButtons.OK, MessageBoxIcon.Information);
    }

    /// <summary>
    /// Initiates the loading process for the currently active tab.
    /// </summary>
    /// <param name="sender">Holds the object instantiating this event</param>
    /// <param name="e">Holds the event arguments</param>
    private void BtnLoadDesign_Click(object sender, EventArgs e)
    {
      try
      {
        var itemLoad = RepositoryHandler.LoadWondrousItem();
        Cursor.Current = Cursors.WaitCursor;
        itemName.Text = itemLoad.Item.Name.Name;

        if (itemLoad.Item.AuraAndCasterLevel.Aura.Any())
        {
          aura1Strength.Text = itemLoad.Item.AuraAndCasterLevel.Aura[0].Strength;
          aura1School.Text = itemLoad.Item.AuraAndCasterLevel.Aura[0].School;
          aura1SubSchool.Text = itemLoad.Item.AuraAndCasterLevel.Aura[0].SubSchool;

          var items = itemLoad.Item.AuraAndCasterLevel.Aura.Count;
          if (items > 1)
          {
            aura2Strength.Text = itemLoad.Item.AuraAndCasterLevel.Aura[1].Strength;
            aura2School.Text = itemLoad.Item.AuraAndCasterLevel.Aura[1].School;
            aura2SubSchool.Text = itemLoad.Item.AuraAndCasterLevel.Aura[1].SubSchool;
          }
          if (items > 2)
          {
            aura3Strength.Text = itemLoad.Item.AuraAndCasterLevel.Aura[2].Strength;
            aura3School.Text = itemLoad.Item.AuraAndCasterLevel.Aura[2].School;
            aura3SubSchool.Text = itemLoad.Item.AuraAndCasterLevel.Aura[2].SubSchool;
          }
          if (items > 3)
          {
            aura4Strength.Text = itemLoad.Item.AuraAndCasterLevel.Aura[3].Strength;
            aura4School.Text = itemLoad.Item.AuraAndCasterLevel.Aura[3].School;
            aura4SubSchool.Text = itemLoad.Item.AuraAndCasterLevel.Aura[3].SubSchool;
          }
        }

        casterLevel.Text = itemLoad.Item.AuraAndCasterLevel.CasterLevel;
        itemSlot.Text = itemLoad.Item.SlotPriceWeight.Slot;
        autoCalcCosts.Checked = itemLoad.Item.AutoCalcCost;

        if (itemLoad.Item.SlotPriceWeight.Price.Any())
        {
          itemPrice1.Value = itemLoad.Item.SlotPriceWeight.Price[0].Price;
          itemPrice1Postfix.Text = itemLoad.Item.SlotPriceWeight.Price[0].PostFix;

          var items = itemLoad.Item.SlotPriceWeight.Price.Count;
          if (items > 1)
          {
            itemPrice2.Value = itemLoad.Item.SlotPriceWeight.Price[1].Price;
            itemPrice2Postfix.Text = itemLoad.Item.SlotPriceWeight.Price[1].PostFix;
          }
          if (items > 2)
          {
            itemPrice3.Value = itemLoad.Item.SlotPriceWeight.Price[2].Price;
            itemPrice3Postfix.Text = itemLoad.Item.SlotPriceWeight.Price[2].PostFix;
          }
          if (items > 3)
          {
            itemPrice4.Value = itemLoad.Item.SlotPriceWeight.Price[3].Price;
            itemPrice4Postfix.Text = itemLoad.Item.SlotPriceWeight.Price[3].PostFix;
          }
          if (items > 4)
          {
            itemPrice5.Value = itemLoad.Item.SlotPriceWeight.Price[4].Price;
            itemPrice5Postfix.Text = itemLoad.Item.SlotPriceWeight.Price[4].PostFix;
          }
        }

        if (itemLoad.Item.Construction.Cost.Any())
        {
          itemCost1.Value = itemLoad.Item.Construction.Cost[0].Cost;

          var items = itemLoad.Item.Construction.Cost.Count;
          if (items > 1)
            itemCost2.Value = itemLoad.Item.Construction.Cost[1].Cost;
          if (items > 2)
            itemCost3.Value = itemLoad.Item.Construction.Cost[2].Cost;
          if (items > 3)
            itemCost4.Value = itemLoad.Item.Construction.Cost[3].Cost;
          if (items > 4)
            itemCost5.Value = itemLoad.Item.Construction.Cost[4].Cost;
        }

        itemWeight.Text = itemLoad.Item.SlotPriceWeight.Weight.Weight;
        itemWeightPostfix.Text = itemLoad.Item.SlotPriceWeight.Weight.PostFix;
        itemDescription.Text = itemLoad.Item.Description.Description;

        if (itemLoad.Item.Construction.Feat.Any())
        {
          itemFeat1.Text = itemLoad.Item.Construction.Feat[0];

          var items = itemLoad.Item.Construction.Feat.Count;
          if (items > 1)
            itemFeat2.Text = itemLoad.Item.Construction.Feat[1];
          if (items > 2)
            itemFeat3.Text = itemLoad.Item.Construction.Feat[2];
        }

        if (itemLoad.Item.Construction.Spell.Any())
        {
          itemSpellLevel1.Text = itemLoad.Item.Construction.Spell[0].Level;
          itemSpellSchool1.Text = itemLoad.Item.Construction.Spell[0].School;
          itemSpell1.Text = itemLoad.Item.Construction.Spell[0].Spell;

          var items = itemLoad.Item.Construction.Spell.Count;
          if (items > 1)
          {
            itemSpellLevel2.Text = itemLoad.Item.Construction.Spell[1].Level;
            itemSpellSchool2.Text = itemLoad.Item.Construction.Spell[1].School;
            itemSpell2.Text = itemLoad.Item.Construction.Spell[1].Spell;
          }
          if (items > 2)
          {
            itemSpellLevel3.Text = itemLoad.Item.Construction.Spell[2].Level;
            itemSpellSchool3.Text = itemLoad.Item.Construction.Spell[2].School;
            itemSpell3.Text = itemLoad.Item.Construction.Spell[2].Spell;
          }
          if (items > 3)
          {
            itemSpellLevel4.Text = itemLoad.Item.Construction.Spell[3].Level;
            itemSpellSchool4.Text = itemLoad.Item.Construction.Spell[3].School;
            itemSpell4.Text = itemLoad.Item.Construction.Spell[3].Spell;
          }
          if (items > 4)
          {
            itemSpellLevel5.Text = itemLoad.Item.Construction.Spell[4].Level;
            itemSpellSchool5.Text = itemLoad.Item.Construction.Spell[4].School;
            itemSpell5.Text = itemLoad.Item.Construction.Spell[4].Spell;
          }
          if (items > 5)
          {
            itemSpellLevel6.Text = itemLoad.Item.Construction.Spell[5].Level;
            itemSpellSchool6.Text = itemLoad.Item.Construction.Spell[5].School;
            itemSpell6.Text = itemLoad.Item.Construction.Spell[5].Spell;
          }
        }

        incSkillReq.Checked = itemLoad.Item.Construction.SkillRequirement.Required;
        if (incSkillReq.Checked)
        {
          wiRankChoices.Text = itemLoad.Item.Construction.SkillRequirement.Ranks;
          wiSkillChoices.Text = itemLoad.Item.Construction.SkillRequirement.Name;
          wiSubSkillChoices.Text = itemLoad.Item.Construction.SkillRequirement.SubSkill;
        }

        incRaceReq.Checked = itemLoad.Item.Construction.RaceRequirement.Required;
        if (incRaceReq.Checked)
          raceChoices.Text = itemLoad.Item.Construction.RaceRequirement.RaceName;

        incText.Checked = itemLoad.Item.Construction.OtherRequirement.Required;
        if (incText.Checked)
          wiOtherConstruction.Text = itemLoad.Item.Construction.OtherRequirement.Other;

        Cursor.Current = Cursors.Default;
      }
      catch (Exception)
      {
        Cursor.Current = Cursors.Default;
        throw;
      }
    }

    /// <summary>
    /// Handles the copy name button clicks.
    /// </summary>
    /// <param name="sender">Holds the object instantiating this event</param>
    /// <param name="e">Holds the event arguments</param>
    private void BtnName_Click(object sender, EventArgs e)
    {
      postName.SelectAll();
      postName.Copy();
      MessageBox.Show(Localize.InfoNameInBufferText, Localize.InfoNameInBufferTitle, MessageBoxButtons.OK, MessageBoxIcon.Information);
    }

    /// <summary>
    /// Shared button bar event handler to past the BB code tags into the description when pressed.
    /// </summary>
    /// <param name="sender">Holds the object instantiating this event</param>
    /// <param name="e">Holds the event arguments</param>
    private void BtnRTFBBCodeInsert_Click(object sender, EventArgs e)
    {
      var insertPoint = itemDescription.SelectionStart;
      itemDescription.Text = itemDescription.Text.Insert(itemDescription.SelectionStart, ((ToolStripButton)sender).Text);
      insertPoint += ((ToolStripButton)sender).Text.Length;
      itemDescription.SelectionStart = insertPoint;
      itemDescription.Focus();
    }

    /// <summary>
    /// Initiates the saving process for the currently active tab.
    /// </summary>
    /// <param name="sender">Holds the object instantiating this event</param>
    /// <param name="e">Holds the event arguments</param>
    private void BtnSaveDesign_Click(object sender, EventArgs e)
    {
      Cursor.Current = Cursors.WaitCursor;
      var itemSave = new WondrousItemSerializedForSaveLoad
      {
        Item = new WondrousItem
        {
          Name = new WondrousItemName { Name = itemName.Text },
          AuraAndCasterLevel = new WondrousItemAuraAndCasterLevel { CasterLevel = casterLevel.Text },
          SlotPriceWeight = new WondrousItemSlotPriceWeightLine
          {
            Slot = itemSlot.Text,
            Weight = new WondrousItemWeight
            {
              Weight = itemWeight.Text,
              PostFix = itemWeightPostfix.Text
            }
          },
          Description = new WondrousItemDescriptionLines { Description = itemDescription.Text },
          Construction = new WondrousItemConstructionLine
          {
            SkillRequirement = new WondrousItemSkillRequirement
            {
              Required = incSkillReq.Checked,
              Ranks = wiRankChoices.Text,
              Name = wiSkillChoices.Text,
              SubSkill = wiSubSkillChoices.Text
            },
            RaceRequirement = new WondrousItemRaceRequirement
            {
              Required = incRaceReq.Checked,
              RaceName = raceChoices.Text
            },
            OtherRequirement = new WondrousItemOtherRequirement
            {
              Required = incText.Checked,
              Other = wiOtherConstruction.Text
            }
          },
          AutoCalcCost = autoCalcCosts.Checked
        }
      };

      if (!string.IsNullOrWhiteSpace(aura1Strength.Text))
        itemSave.Item.AuraAndCasterLevel.Aura.Add(new WondrousItemAura
        {
          Strength = aura1Strength.Text,
          School = aura1School.Text,
          SubSchool = aura1SubSchool.Text
        });

      if (!string.IsNullOrWhiteSpace(aura2Strength.Text))
        itemSave.Item.AuraAndCasterLevel.Aura.Add(new WondrousItemAura
        {
          Strength = aura2Strength.Text,
          School = aura2School.Text,
          SubSchool = aura2SubSchool.Text
        });

      if (!string.IsNullOrWhiteSpace(aura3Strength.Text))
        itemSave.Item.AuraAndCasterLevel.Aura.Add(new WondrousItemAura
        {
          Strength = aura3Strength.Text,
          School = aura3School.Text,
          SubSchool = aura3SubSchool.Text
        });

      if (!string.IsNullOrWhiteSpace(aura4Strength.Text))
        itemSave.Item.AuraAndCasterLevel.Aura.Add(new WondrousItemAura
        {
          Strength = aura4Strength.Text,
          School = aura4School.Text,
          SubSchool = aura4SubSchool.Text
        });

      if (itemPrice1.Value > 0)
      {
        itemSave.Item.SlotPriceWeight.Price.Add(new WondrousItemPrice
        {
          Price = itemPrice1.Value,
          PostFix = itemPrice1Postfix.Text
        });
      }

      if (itemPrice2.Value > 0)
      {
        itemSave.Item.SlotPriceWeight.Price.Add(new WondrousItemPrice
        {
          Price = itemPrice2.Value,
          PostFix = itemPrice2Postfix.Text
        });
      }

      if (itemPrice3.Value > 0)
      {
        itemSave.Item.SlotPriceWeight.Price.Add(new WondrousItemPrice
        {
          Price = itemPrice3.Value,
          PostFix = itemPrice3Postfix.Text
        });
      }

      if (itemPrice4.Value > 0)
      {
        itemSave.Item.SlotPriceWeight.Price.Add(new WondrousItemPrice
        {
          Price = itemPrice4.Value,
          PostFix = itemPrice4Postfix.Text
        });
      }

      if (itemPrice5.Value > 0)
      {
        itemSave.Item.SlotPriceWeight.Price.Add(new WondrousItemPrice
        {
          Price = itemPrice5.Value,
          PostFix = itemPrice5Postfix.Text
        });
      }

      if (itemCost1.Value > 0)
      {
        itemSave.Item.Construction.Cost.Add(new WondrousItemCost
        {
          Cost = itemCost1.Value,
          PostFix = itemPrice1Postfix.Text
        });
      }

      if (itemCost2.Value > 0)
      {
        itemSave.Item.Construction.Cost.Add(new WondrousItemCost
        {
          Cost = itemCost2.Value,
          PostFix = itemPrice2Postfix.Text
        });
      }

      if (itemCost3.Value > 0)
      {
        itemSave.Item.Construction.Cost.Add(new WondrousItemCost
        {
          Cost = itemCost3.Value,
          PostFix = itemPrice3Postfix.Text
        });
      }

      if (itemCost4.Value > 0)
      {
        itemSave.Item.Construction.Cost.Add(new WondrousItemCost
        {
          Cost = itemCost4.Value,
          PostFix = itemPrice4Postfix.Text
        });
      }

      if (itemCost5.Value > 0)
      {
        itemSave.Item.Construction.Cost.Add(new WondrousItemCost
        {
          Cost = itemCost5.Value,
          PostFix = itemPrice5Postfix.Text
        });
      }

      if (!string.IsNullOrWhiteSpace(itemFeat1.Text))
        itemSave.Item.Construction.Feat.Add(itemFeat1.Text);

      if (!string.IsNullOrWhiteSpace(itemFeat2.Text))
        itemSave.Item.Construction.Feat.Add(itemFeat2.Text);

      if (!string.IsNullOrWhiteSpace(itemFeat3.Text))
        itemSave.Item.Construction.Feat.Add(itemFeat3.Text);

      if (!string.IsNullOrWhiteSpace(itemSpellLevel1.Text))
        itemSave.Item.Construction.Spell.Add(new WondrousItemSpell
        {
          Level = itemSpellLevel1.Text,
          School = itemSpellSchool1.Text,
          Spell = itemSpell1.Text
        });

      if (!string.IsNullOrWhiteSpace(itemSpellLevel2.Text))
        itemSave.Item.Construction.Spell.Add(new WondrousItemSpell
        {
          Level = itemSpellLevel2.Text,
          School = itemSpellSchool2.Text,
          Spell = itemSpell2.Text
        });

      if (!string.IsNullOrWhiteSpace(itemSpellLevel3.Text))
        itemSave.Item.Construction.Spell.Add(new WondrousItemSpell
        {
          Level = itemSpellLevel3.Text,
          School = itemSpellSchool3.Text,
          Spell = itemSpell3.Text
        });

      if (!string.IsNullOrWhiteSpace(itemSpellLevel4.Text))
        itemSave.Item.Construction.Spell.Add(new WondrousItemSpell
        {
          Level = itemSpellLevel4.Text,
          School = itemSpellSchool4.Text,
          Spell = itemSpell4.Text
        });

      if (!string.IsNullOrWhiteSpace(itemSpellLevel5.Text))
        itemSave.Item.Construction.Spell.Add(new WondrousItemSpell
        {
          Level = itemSpellLevel5.Text,
          School = itemSpellSchool5.Text,
          Spell = itemSpell5.Text
        });

      if (!string.IsNullOrWhiteSpace(itemSpellLevel6.Text))
        itemSave.Item.Construction.Spell.Add(new WondrousItemSpell
        {
          Level = itemSpellLevel6.Text,
          School = itemSpellSchool6.Text,
          Spell = itemSpell6.Text
        });

      try
      {
        RepositoryHandler.SaveWondrousItem(itemName.Text, itemSave);
        Cursor.Current = Cursors.Default;
      }
      catch (Exception)
      {
        Cursor.Current = Cursors.Default;
        throw;
      }
    }

    /// <summary>
    /// Event catcher such that when the Aura changes, the Sub School choices are updated dynamically
    /// in addition to updating the entry panel.
    /// </summary>
    /// <param name="sender">Holds the object instantiating this event</param>
    /// <param name="e">Holds the event arguments</param>
    private void AuraSchool_TextChanged(object sender, EventArgs e)
    {
      SpellHandlers.SetSubSchoolList(((Control)sender).Text.ToLower(), ((Control)sender).Tag as ComboBox);
      UpdateWondrousItemPostEntry(sender, e);
    }

    /// <summary>
    /// Provides a standard on leave event for controls with Text that need to be camel
    /// capitalised as part of the entry formatting.
    /// </summary>
    /// <param name="sender">Holds the object instantiating this event</param>
    /// <param name="e">Holds the event arguments</param>
    private void CamelCapitalizeOnLeave(object sender, EventArgs e)
    {
      TextHandlers.CamelCapitalize(sender, e);
    }

    /// <summary>
    /// When a spell level or school choice is changed, this event resets the spell list based on the
    /// combination of the level, school and currently active content available
    /// </summary>
    /// <param name="level">The selected spell level from the spell level choices</param>
    /// <param name="school">The selected school from the spell school choices</param>
    /// <param name="comboBox">The combobox control containg the spell names needing to be updated</param>
    private void CommonLevelSchoolChange(string level, string school, ComboBox comboBox)
    {
      var settings = GetCurrentConfigurationSettings();
      var checkState = settings.GetInclusionCheckState();

      SpellHandlers.ResetSpellsList(checkState, level, school, comboBox);
    }

    private void incSkillReq_CheckedChanged(object sender, EventArgs e)
    {
      wiRanksLabel.Enabled = wiRankChoices.Enabled = wiSkillLabel.Enabled =
        wiSkillChoices.Enabled = wiSubSkillChoices.Enabled = incSkillReq.Checked;
    }

    /// <summary>
    /// Event that catches Wondrous Item Name changes and propogates to both the entry name
    /// preview and the entry itself.
    /// </summary>
    /// <param name="sender">Holds the object instantiating this event</param>
    /// <param name="e">Holds the event arguments</param>
    private void ItemName_TextChanged(object sender, EventArgs e)
    {
      postName.Text = itemName.Text;
      UpdateWondrousItemPostEntry(sender, e);
    }

    /// <summary>
    /// Handles changes on the 1st price.
    /// </summary>
    /// <param name="sender">Holds the object instantiating this event</param>
    /// <param name="e">Holds the event arguments</param>
    private void ItemPrice_Changed(object sender, EventArgs e)
    {
      if (autoCalcCosts.Checked)
      {
        var senderControl = ((Control)sender);

        switch (senderControl.Name)
        {
          case "itemPrice1":
            itemCost1.Value = itemPrice1.Value / 2;
            break;
          case "itemPrice2":
            itemCost2.Value = itemPrice2.Value / 2;
            break;
          case "itemPrice3":
            itemCost3.Value = itemPrice3.Value / 2;
            break;
          case "itemPrice4":
            itemCost4.Value = itemPrice4.Value / 2;
            break;
          case "itemPrice5":
            itemCost5.Value = itemPrice5.Value / 2;
            break;
          default:
            return;
        }
      }

      UpdateWondrousItemPostEntry(sender, e);
    }

    /// <summary>
    /// Whenever the word count fires, the current count is compared to the max, and if the max is exceeded
    /// the submission copy buttons are disabled. They re-enable once the word count is below the max again.
    /// </summary>
    /// <param name="sender">Holds the object instantiating this event</param>
    /// <param name="e">Holds the event arguments</param>
    private void ItemWordCount_TextChanged(object sender, EventArgs e)
    {
      long currentWords;
      long.TryParse(itemWordCount.Text, out currentWords);

      long maxWords;
      long.TryParse(safeWordCountMax.Text, out maxWords);

      ShowMyEntryControls(maxWords > 0 && currentWords <= maxWords);
    }

    /// <summary>
    /// Provides a standard on leave event for controls with Text that need to be
    /// all lower case as part of the entry formatting (e.g. spell list in the Construction
    /// details of a Wondrous Item.
    /// </summary>
    /// <param name="sender">Holds the object instantiating this event</param>
    /// <param name="e">Holds the event arguments</param>
    private void MakeLowerOnLeave(object sender, EventArgs e)
    {
      TextHandlers.MakeLower(sender, e);
    }

    /// <summary>
    /// Handler to handle the selection of an item in a must be in the list selection box and the
    /// item typed is not in the list - it displays an information box to the user and opens the
    /// selection box in error.
    /// </summary>
    /// <param name="sender">Holds the object instantiating this event</param>
    /// <param name="e">Holds the event arguments</param>
    private void MustBeInListAndNotInList(object sender, System.ComponentModel.CancelEventArgs e)
    {
      // this is ok if the box has been cleared, if the user submits with no entry they are daft
      // and empty is also used for deselecting multiples.
      var thisControl = (AutoCompleteComboBox)sender;

      if (string.IsNullOrEmpty(thisControl.Text)) return;

      MessageBox.Show(
        AdvisorStrings.SuperStar_MustBeInListAndNotInList_Your_choice_of_ + thisControl.SelectedText +
        AdvisorStrings.SuperStar_MustBeInListAndNotInList_, AdvisorStrings.SuperStar_MustBeInListAndNotInList_Choice_Selection_Error,
        MessageBoxButtons.OK, MessageBoxIcon.Error);

      thisControl.Focus();
      thisControl.SelectionStart = 0;
      thisControl.SelectionLength = thisControl.Text.Length;
      thisControl.DroppedDown = true;
    }

    /// <summary>
    /// Obtains the localised help for the control gaining focus and places it into the advisory panel.
    /// </summary>
    /// <param name="sender">Holds the object instantiating this event</param>
    public void SetHelpText(object sender)
    {
      OwnerSuperStar.HelperTextRtf = string.Empty;
      var control = sender as Control;
      if (control == null) return;
      switch (control.Name)
      {
        case "itemName":
          OwnerSuperStar.HelperTextRtf = LocalizeAdvisor.WondrousItemNameAdvice;
          break;

        default:
          OwnerSuperStar.HelperTextRtf = string.Empty;
          break;
      }
    }

    private void SelectAndGetHelp(object sender, EventArgs e)
    {
      SelectAllText(sender);
      SetHelpText(sender);
    }

    /// <summary>
    /// Captures changed events on spell levels and school first choices
    /// </summary>
    /// <param name="sender">Holds the object instantiating this event</param>
    /// <param name="e">Holds the event arguments</param>
    private void SpellLevelSchool_TextChanged(object sender, EventArgs e)
    {
      switch (((Control)sender).Name)
      {
        case "itemSpellLevel1":
        case "itemSpellSchool1":
          CommonLevelSchoolChange(itemSpellLevel1.Text, itemSpellSchool1.Text, itemSpell1);
          break;
        case "itemSpellLevel2":
        case "itemSpellSchool2":
          CommonLevelSchoolChange(itemSpellLevel2.Text, itemSpellSchool2.Text, itemSpell2);
          break;
        case "itemSpellLevel3":
        case "itemSpellSchool3":
          CommonLevelSchoolChange(itemSpellLevel3.Text, itemSpellSchool3.Text, itemSpell3);
          break;
        case "itemSpellLevel4":
        case "itemSpellSchool4":
          CommonLevelSchoolChange(itemSpellLevel4.Text, itemSpellSchool4.Text, itemSpell4);
          break;
        case "itemSpellLevel5":
        case "itemSpellSchool5":
          CommonLevelSchoolChange(itemSpellLevel5.Text, itemSpellSchool5.Text, itemSpell5);
          break;
        case "itemSpellLevel6":
        case "itemSpellSchool6":
          CommonLevelSchoolChange(itemSpellLevel6.Text, itemSpellSchool6.Text, itemSpell6);
          break;
      }

      UpdateWondrousItemPostEntry(sender, e);
    }

    private void skillChoices_TextChanged(object sender, EventArgs e)
    {
      var settings = GetCurrentConfigurationSettings();
      var checkState = settings.GetInclusionCheckState();

      SkillHandlers.SetSubSkillList(checkState, wiSkillChoices.Text, wiSubSkillChoices);
      UpdateWondrousItemPostEntry(sender, e);
    }

    /// <summary>
    /// Event for control content change events that directly affect the resulting
    /// Wondrous Item entry formatted, bb code or raw.
    /// </summary>
    /// <param name="sender">Holds the object instantiating this event</param>
    /// <param name="e">Holds the event arguments</param>
    private void UpdateWondrousItemPostEntry(object sender, EventArgs e)
    {
      // if there is an update still running, dont start this one.
      if (UpdateIsRunning) return;
      UpdateIsRunning = true;

      WondrousItemEntryBuilder.StartNewEntry();
      WondrousItemEntryBuilder.AppendEntryName(postName.Text);
      WondrousItemEntryBuilder.AppendAuras(
        aura1Strength.Text, aura1School.Text, aura1SubSchool.Text,
        aura2Strength.Text, aura2School.Text, aura2SubSchool.Text,
        aura3Strength.Text, aura3School.Text, aura3SubSchool.Text,
        aura4Strength.Text, aura4School.Text, aura4SubSchool.Text);
      WondrousItemEntryBuilder.AppendCasterLevel(casterLevel.Text);
      WondrousItemEntryBuilder.AppendSlot(itemSlot.Text);
      itemPrice5.Value = itemPrice4.Value == 0 ? 0 : itemPrice5.Value;
      itemPrice5.Value = itemPrice4.Value = itemPrice3.Value == 0 ? 0 : itemPrice4.Value;
      itemPrice5.Value = itemPrice4.Value = itemPrice3.Value = itemPrice2.Value == 0 ? 0 : itemPrice3.Value;
      itemPrice5.Value = itemPrice4.Value = itemPrice3.Value = itemPrice2.Value = itemPrice1.Value == 0 ? 0 : itemPrice2.Value;
      WondrousItemEntryBuilder.AppendPrice(
        itemPrice1.Value, itemPrice1Postfix.Text,
        itemPrice2.Value, itemPrice2Postfix.Text,
        itemPrice3.Value, itemPrice3Postfix.Text,
        itemPrice4.Value, itemPrice4Postfix.Text,
        itemPrice5.Value, itemPrice5Postfix.Text);

      itemWeightPostfix.Text = string.Empty;
      double myWeight;
      if (double.TryParse(itemWeight.Text, out myWeight))
        itemWeightPostfix.Text = myWeight > 1 || myWeight < 0 ? "lbs." : "lb.";

      WondrousItemEntryBuilder.AppendWeight(itemWeight.Text);
      WondrousItemEntryBuilder.AppendDescriptionLine("Description");

      if (itemDescription.Lines.Length == 0 ||
          itemDescription.Text.Equals(string.Empty))
        WondrousItemEntryBuilder.AppendDescriptionLine(string.Empty);
      else
      {
        foreach (var line in itemDescription.Lines)
        {
          WondrousItemEntryBuilder.AppendDescriptionLine(line.Replace("<b>", "[b]").Replace("</b>", "[/b]").Replace("<i>", "[i]").Replace("</i>", "[/i]"));
        }
      }

      WondrousItemEntryBuilder.AppendConstructionLine("Construction");
      WondrousItemEntryBuilder.AppendConstructionFeats(itemFeat1.Text, itemFeat2.Text, itemFeat3.Text);

      // Filter Blanks from Wondrous Item Spells - one pass only need due to disablement of empty selections from form
      SpellHandlers.SwapSpellSlotsIfEmptied(itemSpellLevel5, itemSpellLevel6, itemSpellSchool5, itemSpellSchool6, itemSpell5, itemSpell6);
      SpellHandlers.SwapSpellSlotsIfEmptied(itemSpellLevel4, itemSpellLevel5, itemSpellSchool4, itemSpellSchool5, itemSpell4, itemSpell5);
      SpellHandlers.SwapSpellSlotsIfEmptied(itemSpellLevel3, itemSpellLevel4, itemSpellSchool3, itemSpellSchool4, itemSpell3, itemSpell4);
      SpellHandlers.SwapSpellSlotsIfEmptied(itemSpellLevel2, itemSpellLevel3, itemSpellSchool2, itemSpellSchool3, itemSpell2, itemSpell3);
      SpellHandlers.SwapSpellSlotsIfEmptied(itemSpellLevel1, itemSpellLevel2, itemSpellSchool1, itemSpellSchool2, itemSpell1, itemSpell2);

      if (!itemSpell1.Text.Equals(string.Empty))
      {
        var spellList = new List<WondrousItemSpellChosen>
        {
          new WondrousItemSpellChosen(itemSpellLevel1.Text, itemSpellSchool1.Text, itemSpell1.Text)
        };

        if (!itemSpell2.Text.Equals(string.Empty))
        {
          spellList.Add(new WondrousItemSpellChosen(itemSpellLevel2.Text, itemSpellSchool2.Text, itemSpell2.Text));
          if (!itemSpell3.Text.Equals(string.Empty))
          {
            spellList.Add(new WondrousItemSpellChosen(itemSpellLevel3.Text, itemSpellSchool3.Text, itemSpell3.Text));
            if (!itemSpell4.Text.Equals(string.Empty))
            {
              spellList.Add(new WondrousItemSpellChosen(itemSpellLevel4.Text, itemSpellSchool4.Text, itemSpell4.Text));
              if (!itemSpell5.Text.Equals(string.Empty))
              {
                spellList.Add(new WondrousItemSpellChosen(itemSpellLevel5.Text, itemSpellSchool5.Text, itemSpell5.Text));
                if (!itemSpell6.Text.Equals(string.Empty))
                {
                  spellList.Add(new WondrousItemSpellChosen(itemSpellLevel6.Text, itemSpellSchool6.Text, itemSpell6.Text));
                }
              }
            }
          }
        }

        spellList.Sort((spell1, spell2) => string.Compare(spell1.SpellSpell, spell2.SpellSpell, StringComparison.Ordinal) == 0
          ? string.Compare(spell1.SpellLevel, spell2.SpellLevel, StringComparison.Ordinal)
          : string.Compare(spell1.SpellSpell, spell2.SpellSpell, StringComparison.Ordinal));

        WondrousItemEntryBuilder.AppendConstructionSpells(spellList);
      }

      WondrousItemEntryBuilder.AppendConstructionOther(incSkillReq.Checked, wiRankChoices.Text, wiSkillChoices.Text, wiSubSkillChoices.Text, incRaceReq.Checked, raceChoices.Text, incText.Checked, wiOtherConstruction.Text);

      if (!autoCalcCosts.Checked)
      {
        itemCost5.Value = itemCost4.Value == 0 ? 0 : itemCost5.Value;
        itemCost5.Value = itemCost4.Value = itemCost3.Value == 0 ? 0 : itemCost4.Value;
        itemCost5.Value = itemCost4.Value = itemCost3.Value = itemCost2.Value == 0 ? 0 : itemCost3.Value;
        itemCost5.Value = itemCost4.Value = itemCost3.Value = itemCost2.Value = itemCost1.Value == 0 ? 0 : itemCost2.Value;
      }

      WondrousItemEntryBuilder.AppendCost(
        itemCost1.Value, itemPrice1Postfix.Text, itemCost2.Value, itemPrice2Postfix.Text,
        itemCost3.Value, itemPrice3Postfix.Text, itemCost4.Value, itemPrice4Postfix.Text, itemCost5.Value, itemPrice5Postfix.Text);

      // all formatting now done, so place in situ, start with the word count
      postEntry.Text = WondrousItemEntryBuilder.CloseOffLastLine();
      itemWordCount.Text = TextHandlers.WordCount(postEntry.Text).ToString();

      // Wondrous Item update preview
      var previewRtf = new StringBuilder();
      previewRtf.Append(@"{\rtf1\ansi ");

      foreach (var previewLine in postEntry.Lines)
      {
        previewRtf.Append(previewLine.Replace("[b]", "\\b ").Replace("[/b]", "\\b0 ").Replace("[i]", "\\i ").Replace("[/i]", "\\i0 "));
        previewRtf.Append("\\line ");
      }

      previewRtf.Append("}");
      entryPreview.Rtf = previewRtf.ToString();

      // Wondrous Item visibility toggles
      itemSpellLabel2.Visible = itemSpell2.Visible = itemSpellLevel2.Visible = itemSpellSchool2.Visible = !itemSpell1.Text.Equals(string.Empty);
      itemSpellLabel3.Visible = itemSpell3.Visible = itemSpellLevel3.Visible = itemSpellSchool3.Visible = !itemSpell2.Text.Equals(string.Empty);
      itemSpellLabel4.Visible = itemSpell4.Visible = itemSpellLevel4.Visible = itemSpellSchool4.Visible = !itemSpell3.Text.Equals(string.Empty);
      itemSpellLabel5.Visible = itemSpell5.Visible = itemSpellLevel5.Visible = itemSpellSchool5.Visible = !itemSpell4.Text.Equals(string.Empty);
      itemSpellLabel6.Visible = itemSpell6.Visible = itemSpellLevel6.Visible = itemSpellSchool6.Visible = !itemSpell5.Text.Equals(string.Empty);
      itemLabelFeat3.Visible = itemFeat3.Visible = !itemFeat2.Text.Equals(string.Empty);
      itemCost3.Visible = itemPriceLabel3.Visible = itemPrice3.Visible = itemPrice3Postfix.Visible = itemPrice2.Value != 0;
      itemCost4.Visible = itemPriceLabel4.Visible = itemPrice4.Visible = itemPrice4Postfix.Visible = itemPrice3.Value != 0;
      itemCost5.Visible = itemPriceLabel5.Visible = itemPrice5.Visible = itemPrice5Postfix.Visible = itemPrice4.Value != 0;
      aura3Label.Visible = aura3Strength.Visible = aura3School.Visible = aura3SubSchool.Visible = !aura2School.Text.Equals(string.Empty);
      aura4Label.Visible = aura4Strength.Visible = aura4School.Visible = aura4SubSchool.Visible = !aura3School.Text.Equals(string.Empty) && aura3Label.Visible;
      itemCost1.ReadOnly = itemCost2.ReadOnly = itemCost3.ReadOnly = itemCost4.ReadOnly = itemCost5.ReadOnly = autoCalcCosts.Checked;

      // allow any future update events to run
      UpdateIsRunning = false;
    }
  }
}
